package com.qiall.boot.fileservice;

import com.qiall.ali.Oss;
import com.qiall.assertutil.Assert;
import com.qiall.boot.fileability.FileService;
import com.qiall.boot.fileability.request.SetFileInfoDTO;
import com.qiall.boot.fileservice.data.eitity.FileInfo;
import com.qiall.boot.fileservice.data.eitity.enums.FileSourceTypeEnum;
import com.qiall.boot.fileservice.data.eitity.enums.UploadStatusEnum;
import com.qiall.boot.fileservice.data.mapper.FileInfoMapper;
import com.qiall.boot.fileservice.data.properties.OssProperties;
import com.qiall.boot.fileability.request.UploadFileResponse;
import com.qiall.boot.fileservice.impl.BaseFileServiceProxy;
import com.qiall.boot.fileservice.impl.OssService;
import com.qiall.boot.fileservice.impl.fileuploadSuccessEvent.UploadSuccessEvent;
import com.qiall.boot.fileservice.trans.FileDataTrans;
import com.qiall.common.exception.BusinessException;
import com.qiall.common.exception.BusinessResult;
import com.qiall.common.exception.ResultCode;
import com.qiall.common.request.BaseRequest;
import com.qiall.user.ability.entity.UserInfoDTO;
import com.qiall.user.ability.service.user.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

@RestController
@RequestMapping("/file")
public class FileUploadController {


    @Autowired
    private FileInfoMapper fileInfoMapper;

    @Autowired
    private OssService ossService;

    private static final Integer INNER_USER_ID = -1;

    private static int MAX_CONTEXT_TYPE = 64;

    @DubboReference
    private UserService userService;

    @Autowired
    private FileService fileService;

    @Autowired
    private BaseFileServiceProxy baseFileServiceProxy;

    /**
     *
     * @param file
     * @param accessToken
     * @param fileSourceType
     * @see com.qiall.boot.fileservice.data.eitity.enums.FileSourceTypeEnum
     * @param fromId 第三方文件id
     * @return
     *
     */
    @RequestMapping("/upload")
    public BusinessResult<UploadFileResponse> upload(@RequestBody MultipartFile file,
                                                     @RequestParam String accessToken,
                                                     @RequestParam(name = "fileSourceType", required = false, defaultValue = "OSS") String fileSourceType,
                                                     @RequestParam String fromId) {
        Assert.notNull(accessToken, "用户未登陆");
        BaseRequest baseRequest = new BaseRequest();
        baseRequest.setAccessToken(accessToken);
        BusinessResult<UserInfoDTO> result = userService.getUserInfoByAuthCode(baseRequest);
        Assert.notNull(result.getBody(), "用户未登陆");
        FileSourceTypeEnum fileSourceTypeEnum = FileSourceTypeEnum.ofDesc(fileSourceType);
        FileInfo fileInfo = buildFileInfo(file, fileSourceTypeEnum,fromId);
        if(!fileSourceTypeEnum.equals(FileSourceTypeEnum.BAY_FILES)){
            new Thread(() -> {
                baseFileServiceProxy.getBaseFileService(fileSourceTypeEnum).uploadFile(file, fileInfo.getId());
            }).start();
        }
        fileInfoMapper.insert(fileInfo);
        // 上传成功文件信息写入db
        SetFileInfoDTO setFileInfoDTO = new SetFileInfoDTO();
        setFileInfoDTO.setAccessToken(accessToken);
        setFileInfoDTO.setId(fileInfo.getId());
        fileService.setFileUserInfo(setFileInfoDTO);
        UploadFileResponse uploadFileResponse = new UploadFileResponse();
        uploadFileResponse.setId(fileInfo.getId());
        return BusinessResult.success(uploadFileResponse);
    }


    /**
     * 内部文件上传返回下载地址
     *
     * @param file
     * @return
     */
    @PostMapping("/innerUpload")
    public BusinessResult<String> innerUpload(@RequestParam("file") MultipartFile file, @RequestParam(name = "fileSourceType", required = false, defaultValue = "OSS") String fileSourceType,String fromId) {
        FileSourceTypeEnum fileSourceTypeEnum = FileSourceTypeEnum.ofDesc(fileSourceType);
        FileInfo fileInfo = buildFileInfo(file, fileSourceTypeEnum,fromId);
        fileInfo.setUploaderId(INNER_USER_ID);
        fileInfo.setUploadStatus(UploadStatusEnum.已上传.getCode());
        // 上传成功文件信息写入db
        fileInfoMapper.insert(fileInfo);
        String url = baseFileServiceProxy.getBaseFileService(fileSourceTypeEnum).uploadFileInner(file, fileInfo.getId());
        //返回文件下载地址
        return BusinessResult.success(url);
    }

    @GetMapping("/getFileUrl")
    public BusinessResult<String> getFileUrl(@RequestParam("fileId") Integer fileId) {

        FileInfo fileInfo=fileInfoMapper.select(fileId);
        Assert.notNull(fileInfo,"文件不存在");
        FileSourceTypeEnum fileSourceTypeEnum = FileSourceTypeEnum.ofCode(fileInfo.getFromType());
        String tmpUrl=baseFileServiceProxy.getBaseFileService(fileSourceTypeEnum).getDownLoadUrl(fileInfo.getFromId());
        return BusinessResult.success(tmpUrl);
    }

    private String buildObjectName(String fileName) {
        long time = System.currentTimeMillis();
        return time + fileName;
    }

    @Autowired
    private StreamProcessNotInServer buyFilesService;
    private FileInfo buildFileInfo(MultipartFile file, FileSourceTypeEnum fileSourceTypeEnum,String fromId) {
      if(fileSourceTypeEnum.equals(FileSourceTypeEnum.BAY_FILES)){
         return buyFilesService.buildFileInfo(fromId);
      }
        String contentType = file.getContentType();
        if (contentType.length() > MAX_CONTEXT_TYPE) {
            contentType = contentType.substring(0, MAX_CONTEXT_TYPE);
        }
        String fileName = file.getOriginalFilename();
        long size = file.getSize();
        FileInfo fileInfo = new FileInfo();
        Integer maxId = fileInfoMapper.selectMaxId();
        Integer id = maxId == null ? 1 : maxId + 1;
        fileInfo.setId(id);
        fileInfo.setFileName(fileName);
        fileInfo.setContextType(contentType);
        fileInfo.setFileSize(size);
        fileInfo.setFromType(fileSourceTypeEnum.getCode());
        fileInfo.setUploadStatus(UploadStatusEnum.上传中.getCode());
        return fileInfo;
    }


}
